package prefix.util;

import java.io.File;
import java.math.RoundingMode;
import java.text.CharacterIterator;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.text.StringCharacterIterator;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;

public class FormatUtil {

    private static final Pattern SCRIPT = Pattern.compile("<SCRIPT>", Pattern.CASE_INSENSITIVE);

    private static final Pattern SCRIPT_END = Pattern.compile("</SCRIPT>", Pattern.CASE_INSENSITIVE);

    /**
     * This method should format the amount of time left, e.g. before a loan
     * closes. The time should be formatted according to the following rules: --
     * if under one hour, show minutes only, e.g. "56 minutes" -- if under one
     * day, show hours and minutes, e.g. "7 hours 5 minutes" -- if over one day,
     * show days and hours, e.g. "5 days 6 hours" -- if the argument ms is less
     * than 0, an empty string is returned.
     * 
     * @param ms
     * @return
     */

    @SuppressWarnings("boxing")
    public static String formatLongTimeLeft(long ms) {
        if (ms < 0) {
            return String.format("%d 小时, %d 分钟", 0, 0);
        }
        long minutes = ms / 1000 / 60;
        long hours = minutes / 60;
        minutes = minutes % 60;
        long days = hours / 24;
        hours = hours % 24;

        return days > 0 ? String.format("%d 天, %d 小时", days, hours) : String.format("%d 小时, %d 分钟", hours, minutes);
    }

    /**
     * This method should format the amount of time left, e.g. before a loan
     * closes. The time should be formatted according to the following rules: --
     * if under one hour, show minutes only, e.g. "56m" -- if under one day,
     * show hours and minutes, e.g. "7h 5m" -- if over one day, show days and
     * hours, e.g. "5d 6h" -- if the argument ms is less than 0, an empty string
     * is retuned.
     * 
     * @param ms
     * @return
     */

    @SuppressWarnings("boxing")
    public static String formatTimeLeft(long ms) {
        if (ms < 0) {
            return String.format("%dh %dm", 0, 0);
        }
        long minutes = ms / 1000 / 60;
        long hours = minutes / 60;
        minutes = minutes % 60;
        long days = hours / 24;
        hours = hours % 24;

        return days > 0 ? String.format("%dd %dh", days, hours) : String.format("%dh %dm", hours, minutes);
    }

    /**
     * Obfuscates an account number by replacing all but the last 3 digits with
     * "x", e.g. 123456 -> xxx456
     * 
     * @param s
     */
    public static String obfuscateAccount(String s) {
        if (s == null) {
            return null;
        }

        if (s.length() <= 3)
            return s;

        StringBuilder sb = new StringBuilder(s.length());
        for (int i = 0; i < s.length() - 3; i++) {
            sb.append('x');
        }
        sb.append(s.substring(s.length() - 3));
        return sb.toString();
    }

    public static String formatDaysHours(double decimalDays) {
        int hours = (int) Math.round(decimalDays * 24);
        int days = hours / 24;
        hours -= days * 24;
        String dayUnit = (days > 1) ? " days " : " day ";
        String hourUnit = (hours > 1) ? " hours" : " hour";
        String str = String.valueOf(days) + dayUnit + " and " + String.valueOf(hours) + hourUnit;
        return str;
    }

    /**
     * Return a two decimal amount, e.g 3.14159 -> 3.14
     * 
     * @param d
     * @return
     */
    public static String formatTwoDecimalAmount(double d) {
        DecimalFormat df = new DecimalFormat("0.00");
        return df.format(d);
    }

    /**
     * Return an amount in cash form, no decimals and commas, e.g. 35000.00 ->
     * ¥35,000
     * 
     * @param d
     * @return
     */
    public static String formatMoneyNoDecimal(double d) {
        return new DecimalFormat("¥###,###,##0").format(d);
    }

    /**
     * Return an amount in cash form, no decimals and commas, e.g. 35,000 ->
     * 35000
     * 
     * @param str
     * @return
     */
    public static double formatCurrencyWithourUnit(String str) {
        try {
            return new DecimalFormat("###,###,##0").parse(str).doubleValue();
        } catch (ParseException e) {
            return 0d;
        }
    }

    /**
     * Return an amount in cash form, no decimals and commas, e.g. ¥35,000 ->
     * 35000
     * 
     * @param str
     * @return
     */
    public static double formatCurrency(String str) {
        try {
            return new DecimalFormat("¥###,###,##0").parse(str).doubleValue();
        } catch (ParseException e) {
            return 0d;
        }
    }

    /**
     * Return an amount in cash form,displaying 12 decimals
     * 35000.3938759283875932 -> ¥35,000.934882938398t93
     * 
     * @param d
     * @return
     */
    public static String formatMoney12Decimals(double d) {
        return new DecimalFormat("¥###,###,##0.000000000000").format(d);
    }

    /**
     * Mike: The name of the method is confused. There is actually no decimal in
     * the returned value, e.g. 35000.00 -> ¥35,000.
     * 
     * @param d
     * @return e.g. 35000.00 -> ¥35,000
     */
    public static String formatMoneyTwoDecimal(double d) {
        return new DecimalFormat("¥###,###,##0").format(d);
    }

    public static String formatDoubleNoDecimal(double d) {
        return new DecimalFormat("########0").format(d);
    }

    public static void main(String[] args) {
        double d = 0.11014974238350406;
        System.out.println(formatPercentageTwoDecimal(d));
    }

    /**
     * Return an amount in cash form, no decimals and commas, e.g. 35000.00 ->
     * ¥35,000
     * 
     * @param d
     * @return
     */
    public static String formatNumberNoDecimal(double d) {
        return new DecimalFormat("###,###,##0").format(d);
    }

    public static Double formatDoubleWithDecimal(String s) {
        double d = 0.00;
        try {
            d = Double.valueOf(s.trim()).doubleValue();
            DecimalFormat df = new DecimalFormat("#########0.00");
            return new Double(df.format(d)).doubleValue();

        } catch (NumberFormatException nfe) {
            nfe.printStackTrace();
        }
        // if the value cannot be made formatted, return the original
        return d;
    }

    /**
     * 
     * @param pattern
     * @param value
     *            :should be a number
     * @return:String
     */
    public static String formatNumberWithPattern(String pattern, Object value) {
        if (value == null)
            return null;
        String result = null;
        try {
            Double d = Double.valueOf(value.toString());
            DecimalFormat df = new DecimalFormat(pattern);
            result = df.format(d.doubleValue());
        } catch (NumberFormatException nfe) {
            nfe.printStackTrace();
        }
        return result;
    }

    /**
     * Return an amount in cash form with decimals and commas, e.g. 35000 ->
     * ¥35,000
     * 
     * @param d
     * @return
     */
    public static String formatMoneyWithoutDecimal(double d) {
        String ret = new DecimalFormat("¥###,###,##0").format(d);
        if (ret.equals("-¥0")) {
            ret = "¥0";
        }
        return ret;
    }

    /**
     * Return an amount in cash form with decimals and commas, e.g. 35000.00 ->
     * ¥35,000.00
     * 
     * @param d
     * @return
     */
    public static String formatMoneyWithDecimal(double d) {
        String ret = new DecimalFormat("¥###,###,##0.00").format(d);
        if (ret.equals("-¥0.00")) {
            ret = "¥0.00";
        }
        return ret;
    }

    /**
     * Return an amount with decimals and commas, e.g. 35000.00 -> 35,000.00
     * 
     * @param d
     * @return
     */
    public static String formatDoubleWithDecimalAndCommas(double d) {
        String ret = new DecimalFormat("###,###,##0.00").format(d);
        if (ret.equals("-0.00")) {
            ret = "0.00";
        }
        return ret;
    }

    public static String formatDoubleWithDecimal(double d) {
        String ret = new DecimalFormat("########0.00").format(d);
        if (ret.equals("-0.00")) {
            ret = "0.00";
        }
        return ret;

    }

    public static String formatPercentageTwoDecimal(double d) {
        return new DecimalFormat("#0.00%").format(d);
    }

    public static String formatPercentageFourDecimal(double d) {
        return new DecimalFormat("#0.0000%").format(d);
    }

    public static String formatPercentageTwoDecimalNoSign(double d) {
        return new DecimalFormat("#0.00").format(d * 100);
    }

    public static String formatPercentage(double d) {
        return new DecimalFormat("#0%").format(d);
    }

    public static String formatPercentageNoSign(double d) {
        return new DecimalFormat("#0").format(Math.round(d * 100));
    }

    public static String getAge(Date dateOfBirth) {
        Calendar dob = Calendar.getInstance();
        dob.setTime(dateOfBirth);
        Calendar today = Calendar.getInstance();
        int age = today.get(Calendar.YEAR) - dob.get(Calendar.YEAR);
        if (today.get(Calendar.DAY_OF_YEAR) <= dob.get(Calendar.DAY_OF_YEAR))
            age--;
        return Integer.toString(age);
    }

    /**
     * Parse date from string. Used by public marketing jsp pages
     */
    public static Date parseDate(String dateString) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        ParsePosition pp = new ParsePosition(0);
        Date d = formatter.parse(dateString, pp);

        return d;
    }

    /**
     * Is a Date before another date. Used by public marketing jsp pages
     */
    public static boolean isABeforeB(Date myDate, String dateString, String dateADays, String dateBDays) {
        Calendar myCalendarA = Calendar.getInstance();
        myCalendarA.setTime(myDate);

        Calendar myCalendarB = Calendar.getInstance();

        if (!"today".equals(dateString)) {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
            ParsePosition pp = new ParsePosition(0);
            Date d = formatter.parse(dateString, pp);
            myCalendarB.setTime(d);
        }

        int numDaysA = Integer.parseInt(dateADays);
        int numDaysB = Integer.parseInt(dateBDays);

        myCalendarA.add(Calendar.DATE, numDaysA);

        myCalendarB.add(Calendar.DATE, numDaysB);

        return myCalendarA.before(myCalendarB);
    }

    /*
     * isABeforeB(date, string, int int) isAAfterB(date, string, int int)
     */

    /**
     * Is a Date after another date. Used by public marketing jsp pages
     */
    public static boolean isAAfterB(Date myDate, String dateString, String dateADays, String dateBDays) {
        Calendar myCalendarA = Calendar.getInstance();
        myCalendarA.setTime(myDate);

        Calendar myCalendarB = Calendar.getInstance();

        if (!"today".equals(dateString)) {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
            ParsePosition pp = new ParsePosition(0);
            Date d = formatter.parse(dateString, pp);
            myCalendarB.setTime(d);
        }

        int numDaysA = Integer.parseInt(dateADays);
        int numDaysB = Integer.parseInt(dateBDays);

        myCalendarA.add(Calendar.DATE, numDaysA);

        myCalendarB.add(Calendar.DATE, numDaysB);

        return myCalendarA.after(myCalendarB);
    }

    /**
     * This method overloads formMoneyWithDecimal when the input is a string
     * Will Convert the String to a double, and will return the String value if
     * there is an error @ param s @ return
     */
    public static String formatMoneyWithDecimal(String s) {
        try {
            double d = Double.valueOf(s.trim()).doubleValue();
            return new DecimalFormat("¥###,###,##0.00").format(d);
        } catch (NumberFormatException nfe) {
            nfe.printStackTrace();
        }
        // if the value cannot be made formatted, return the original
        return s;
    }

    /**
     * This method overloads formMoney12Decimal when the input is a string Will
     * Convert the String to a double, and will return the String value if there
     * is an error @ param s @ return
     */
    public static String formatMoney12Decimal(String s) {
        try {
            double d = Double.valueOf(s.trim()).doubleValue();
            return new DecimalFormat("¥###,###,##0.00000000000000").format(d);
        } catch (NumberFormatException nfe) {
            nfe.printStackTrace();
        }
        // if the value cannot be made formatted, return the original
        return s;
    }

    public static String formatMoneyNoDecimal(String s) {
        try {
            double d = Double.valueOf(s.trim()).doubleValue();
            return new DecimalFormat("¥###,###,##0").format(d);
        } catch (NumberFormatException nfe) {
            nfe.printStackTrace();
        }
        // if the value cannot be made formatted, return the original
        return s;
    }

    /**
     * This method will return the String with no decimals WITHOUT ROUNDING from
     * the input. IF the input is malformed, the orginal input is returned. 0.28
     * -> 0 @ param s @ return
     */
    public static String formatNumberNoDecimalNoRound(String s) {
        try {
            double d = Double.valueOf(s.trim()).doubleValue();
            d = Math.floor(d);
            return new DecimalFormat("###,###,##0").format(d);
        } catch (NumberFormatException nfe) {
            nfe.printStackTrace();
        }
        // if the value cannot be made formatted, return the original
        return s;
    }

    /**
     * Open-ended date formatting function
     * 
     * @param s
     * @param d
     * @return
     */
    public static String dateFormat(String s, Date d) {
        if (d == null)
            return null;
        DateFormat df = new SimpleDateFormat(s);
        return df.format(d);
    }

    public static String formatDate(Date d) {
        SimpleDateFormat format = new SimpleDateFormat("MM/d/yyyy HH:mm:ss");
        if (d != null)
            return format.format(d);
        return "N/A";
    }

    public static String formatDateTimeRough(Date d) {
        if (d == null)
            return null;
        String dateString = new SimpleDateFormat("M/d/yy (EEEE - noon)").format(d);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(d);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        String timeString = "noon";
        if (hour < 7) {
            timeString = "early morning";
        } else if (hour < 12) {
            timeString = "morning";
        } else if (hour < 17) {
            timeString = "afternoon";
        } else if (hour < 20) {
            timeString = "evening";
        } else {
            timeString = "late night";
        }
        return dateString.replaceAll("noon", timeString);
    }

    /**
     * Format text for display in the browser. Conversions that are performed: *
     * text followed by a newline is wrapped in paragraph tags (
     * <p>
     * )
     * 
     * Note that any HTML-special characters in the text will be encoded, e.g. *
     * ">" -> "&lt;"
     * 
     * Thus, this text should be safe to show unescaped in an HTML page.
     * 
     * @param s
     * @return
     */
    public static String formatTextForDisplay(String s) {

        String START_PARAGRAPH = "<p>";
        String END_PARAGRAPH = "</p>";

        // first off, make the String HTML safe
        String temp = StringEscapeUtils.escapeHtml(s);

        if (temp == null || temp.length() == 0)
            return "";
        StringBuilder sb = new StringBuilder(temp.length());
        // always start with a "<p>"
        sb.append(START_PARAGRAPH);

        // replace every "\n" with </p><p>"
        sb.append(temp.replace("\n", END_PARAGRAPH + START_PARAGRAPH));

        // end the string with </p>
        sb.append(END_PARAGRAPH);
        return sb.toString();

    }

    public static String formatTextForDisplayWithoutP(String s) {

        String START_PARAGRAPH = "<p>";
        String END_PARAGRAPH = "</p>";

        // first off, make the String HTML safe
        String temp = StringEscapeUtils.escapeHtml(s);

        if (temp == null || temp.length() == 0)
            return "";
        StringBuilder sb = new StringBuilder(temp.length());

        sb.append(temp.replace("\n", END_PARAGRAPH + START_PARAGRAPH));

        return sb.toString();

    }

    /**
     * This method takes three arguments and depending on the correct usage of
     * plural or cingular values will return the correct amount.
     * 
     * @param double num the number to test
     * @param String
     *            cingular
     * @param String
     *            plural @ return the plural value except if the num is exactly
     *            one
     */
    public static String singularPluralFormatter(double num, String cingular, String plural) {
        if (num == 1) {
            return cingular;
        }
        return plural;
    }

    /**
     * This method takes in a Date object and returns how many days have passed
     * from said Date to the present Date
     * 
     * @param double originDate @ return the number of days
     */
    @SuppressWarnings("boxing")
    public static int daysFromDate(Date origin) {
        Date currentDate = new Date();
        int dayDelta = 1;
        // we get the millisecond delta between the two dates and divide by the
        // number of millis in a day
        Long milliDelta = (currentDate.getTime() - origin.getTime()) / (3600 * 24 * 1000);
        dayDelta = Integer.parseInt(String.valueOf(milliDelta));
        return dayDelta;
    }

    /**
     * Cleans the input String so it can be displayed as-is in a Javascript
     * string in an HTML page. Specifically, this method ensures that there are
     * no unescaped double-quotes that could possibly break the enclosing
     * double-quotes.
     * 
     * @param in
     * @return
     */
    public static String cleanForJavascript(String in) {

        String result = in.replaceAll("\"", "\\\\\"");
        // System.out.println(result);

        return result;

    }

    /**
     * Clips a string to the given length if the String exceeds that length. If
     * clipping occurs, the string is shortened to (length - 3) characters, and
     * then ... is appended to the end, e.g. clipString("hamburger", 6) =>
     * "ham..."
     * 
     * Null inputs or lengths <= 3 will result in the input being returned.
     * 
     * @param s
     *            Input string to clip
     * @param length
     *            Final length of the resulting string
     * @return the clipped string
     */
    public static String clipString(String s, int length) {

        if (s == null)
            return s;

        if (s.length() <= length || s.length() <= 3 || s.length() <= length || length < 1) {
            return s;
        }

        return (s.substring(0, length - 3) + "...");

    }

    // ================================== OC4J-specific cookie encoding
    // ==================================

    // paired array of characters and their replacements
    static String[][] replacements = { { "@", "@40" }, { "%", "@25" }, { " ", "@20" }, { ",", "@2c" }, { ";", "@3b" }, };

    /**
     * Encodes string to sidestep the OC4J cookie-renaming-and-encoding feature
     * in 10.1.3.2; see
     * http://forums.oracle.com/forums/thread.jspa?threadID=519580 for more
     * details.
     * 
     * Null input will result in null output
     * 
     * This function will encode the following characters: '%' : '%25' <space> :
     * '%20' ',' : '%2c' ';' : '%3b'
     * 
     * @param in
     *            String to encode
     * @return encoded String
     */
    public static String encodeForOC4JCookie(String in) {

        if (in == null || "".equals(in))
            return in;

        String result = in;

        for (String[] replacement : replacements) {
            result = result.replaceAll(replacement[0], replacement[1]);
        }
        return result;
    }

    /**
     * Decodes string to sidestep the OC4J cookie-renaming-and-encoding feature
     * in 10.1.3.2; see
     * http://forums.oracle.com/forums/thread.jspa?threadID=519580 for more
     * details.
     * 
     * Null input will result in null output
     * 
     * This function will decode the following characters: ';' : '%3b' ',' :
     * '%2c' <space> : '%20' '%' : '%25'
     * 
     * @param in
     *            String to encode
     * @return encoded String
     */
    public static String decodeForOC4JCookie(String in) {

        if (in == null || "".equals(in))
            return in;

        String result = in;

        for (int i = replacements.length - 1; i >= 0; i--) {
            String[] replacement = replacements[i];
            result = result.replaceAll(replacement[1], replacement[0]);
        }

        return result;
    }

    /**
     * Compresses consecutive whitespace characters to one space character, e.g.
     * 'This is great' => 'This is great'. For best results, the string should
     * be trimmed either before or after execution.
     * 
     * @param s
     * @return
     */
    public static String compressWhitespace(String s) {
        String replaceAll = s.replaceAll("\\s+", " ");
        System.out.println(replaceAll);
        return replaceAll;
    }

    // ================================== end OC4J-specific cookie encoding
    // ==================================

    /*
     * Method for easy access to actor screenname through struts tags
     * 
     * @parameter long loan id
     * 
     * @returns String username
     */

    /**
     * Escape characters for text appearing in HTML markup. Used when user has
     * control of the text and we need to protect against multiple attacks
     * including XSS, tag breakup, or any code insertion.
     * 
     * Note, this is a heavy call that should be used when needed
     * 
     * Protects against Cross Site Scripting (XSS) hacks. This method escapes
     * all characters recommended by the Open Web App Security Project - <a
     * href='http://www.owasp.org/index.php/Cross_Site_Scripting'>link</a>.
     * 
     * <The following characters are replaced with corresponding HTML character
     * entities :
     * <tr>
     * <th>Character</th>
     * <th>Encoding</th>
     * </tr>
     * <tr>
     * <td><</td>
     * <td>&lt;</td>
     * </tr>
     * <tr>
     * <td>></td>
     * <td>&gt;</td>
     * </tr>
     * <tr>
     * <td>&</td>
     * <td>&amp;</td>
     * </tr>
     * <tr>
     * <td>"</td>
     * <td>&quot;</td>
     * </tr>
     * <tr>
     * <td>'</td>
     * <td>&#039;</td>
     * </tr>
     * <tr>
     * <td>(</td>
     * <td>&#040;</td>
     * </tr>
     * <tr>
     * <td>)</td>
     * <td>&#041;</td>
     * </tr>
     * <tr>
     * <td>#</td>
     * <td>&#035;</td>
     * </tr>
     * <tr>
     * <td>%</td>
     * <td>&#037;</td>
     * </tr>
     * <tr>
     * <td>;</td>
     * <td>&#059;</td>
     * </tr>
     * <tr>
     * <td>+</td>
     * <td>&#043;</td>
     * </tr>
     * <tr>
     * <td>-</td>
     * <td>&#045;</td>
     * </tr>
     * <tr>
     * <td>NEWLINE</td>
     * <td>""</td>
     * </tr>
     * <tr>
     * <td><SCRIPT></td>
     * <td>&lt;SCRIPT></td>
     * </tr>
     * 
     * 
     * <P>
     * Note that JSTL's {@code <c:out>} escapes <em>only the first 
     * five</em> of the above characters.
     */
    public static String escapeString(String i) {
        // first remove newlines
        // Windows Newlines
        String str = i.replaceAll("\\r\\n", "");
        // Unix newline
        str = str.replaceAll("\\n", "");

        // escape all special chars
        final StringBuilder result = new StringBuilder();
        final StringCharacterIterator iterator = new StringCharacterIterator(str);
        char character = iterator.current();
        while (character != CharacterIterator.DONE) {
            if (character == '<') {
                result.append("&lt;");
            } else if (character == '>') {
                result.append("&gt;");
            } else if (character == '&') {
                result.append("&amp;");
            } else if (character == '\"') {
                result.append("&quot;");
            } else if (character == '\'') {
                result.append("&#039;");
            } else if (character == '(') {
                result.append("&#040;");
            } else if (character == ')') {
                result.append("&#041;");
            } else if (character == '#') {
                result.append("&#035;");
            } else if (character == '%') {
                result.append("&#037;");
            } else if (character == ';') {
                result.append("&#059;");
            } else if (character == '+') {
                result.append("&#043;");
            } else if (character == '-') {
                result.append("&#045;");
            } else {
                // the char is not a special one
                // add it to the result as is
                result.append(character);
            }
            character = iterator.next();
        }
        // BREAKING <SCRIPT> tags
        String temp = result.toString();
        Matcher matcher = SCRIPT.matcher(temp);
        temp = matcher.replaceAll("&lt;SCRIPT>");
        matcher = SCRIPT_END.matcher(result);
        temp = matcher.replaceAll("&lt;/SCRIPT>");
        return temp;
    }

    /*
     * Method used to convert from State specific late payment fee to encompas
     * the fraction of the total loan the current promissory note is presenting.
     */
    public static String parseLateFee(String str, double fraction) {
        String result = "";
        int dollarIndex = str.indexOf("¥");
        if (str.length() == 3) {
            String temp = str.replace('¥', ' ');
            double loanFrac = Double.valueOf(temp) * fraction;
            result = "¥" + OverallUtil.round2Decimal(loanFrac, RoundingMode.CEILING);

        } else if (dollarIndex == -1) {
            result = str;

        } else {
            String[] feeString = new String[2];
            feeString[0] = str.substring(0, dollarIndex);
            feeString[1] = str.substring(dollarIndex + 1, str.length());
            double loanFrac = Double.valueOf(feeString[1]) * fraction;
            result = feeString[0] + "¥" + OverallUtil.round2Decimal(loanFrac, RoundingMode.CEILING);

        }
        return result;

    }

    /*
     * Filter out any potential XSS attacks
     */
    public static String sanitize(String input) {

        return input.replaceAll("(?i)<script.*?>.*?</script.*?>", "") // case 1
                .replaceAll("(?i)<.*?javascript:.*?>.*?</.*?>", "") // case 2
                .replaceAll("(?i)<.*?\\s+on.*?>.*?</.*?>", ""); // case 3

    }

    public static String truncateText(String pTextTotTruncate, int pMaxLength) {
        if (pTextTotTruncate.length() <= pMaxLength)
            return pTextTotTruncate;
        String textToReturn = pTextTotTruncate.substring(0, pMaxLength);
        if (textToReturn.lastIndexOf(" ") >= 0)
            textToReturn = textToReturn.substring(0, textToReturn.lastIndexOf(" ")) + "...";
        return textToReturn;
    }

    // amassillo - 2009/09/04
    public static String formatFileSizeOnKbytes(String dir, String fileName) {
        File v_cvs_file = new File(dir + File.separator + fileName);
        if (v_cvs_file.exists())
            return new DecimalFormat("###,##0kb").format(v_cvs_file.length() / (double) 1024);
        return "";
    }

    /*
     * generate a random number from 0 to max, to be used by jsp
     */
    public static int randomNumInRange(int max) {
        return new Random().nextInt(max);
    }

    public static String trim(String str) {
        String s = str.replace("\"", "").trim();
        return s;
    }

    public static Date createDateFromStringWithFormat(String strDate, String format) {
        if (StringUtils.isEmpty(strDate) || StringUtils.isEmpty(format)) {
            return null;
        }
        try {
            SimpleDateFormat dateformat = new SimpleDateFormat(format);
            return dateformat.parse(strDate);
        } catch (Throwable e) {
            return null;
        }

    }

    /**
     * Return an amount in cash form with decimals and commas, e.g. 35000.00 ->
     * ¥35,000.00 -35000.00 -> (¥35,000.00)
     * 
     * @param d
     * @return
     */
    public static String formatAbsoluteValueNumber(double d) {
        String ret = new DecimalFormat("¥###,###,##0.00").format(d);
        if (ret.equals("-¥0.00")) {
            ret = "¥0.00";
        }
        if (ret.startsWith("-")) {
            ret = ret.replaceFirst("-", "(").concat(")");
        }
        return ret;
    }

    /**
     * Return an amount in cash form with decimals and commas, e.g. 35000.00 ->
     * ¥35,000.00 -35000.00 -> (¥35,000.00)
     * 
     * @param d
     * @param isNegative
     *            (true if it must be formatted as negative)
     * @return
     */
    public static String formatAbsoluteValueNumber(double d, boolean isNegative) {
        String ret = new DecimalFormat("¥###,###,##0.00").format(d);
        if (ret.equals("-¥0.00")) {
            ret = "¥0.00";
        }
        ret = (isNegative) ? ("(" + ret.concat(")")).replaceFirst("-", "") : ret;
        return ret;
    }

    /**
     * Formats a free-form US phone number (10 digits) adding hyphens. E.g.:
     * 1112223333 => 111-222-3333
     * 
     * @param phone
     *            phone number
     */
    public static String formatPhone(String phone) {
        Pattern phonePartsPattern = Pattern.compile("(\\d{3}).*(\\d{3}).*(\\d{4})\\s*(x\\d{3})?");
        Matcher phonePartsMatcher = phonePartsPattern.matcher(phone);
        if (phonePartsMatcher.matches()) {
            String formattedPhone = phonePartsMatcher.group(1) + "-" + phonePartsMatcher.group(2) + "-"
                    + phonePartsMatcher.group(3);
            String extension = phonePartsMatcher.group(4);
            if (extension != null && !extension.isEmpty()) {
                formattedPhone += " " + extension;
            }
            return formattedPhone;
        }
        return phone;
    }
}
